package controls{
	import flash.display.DisplayObject;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	import mx.collections.ArrayCollection;
	import mx.collections.IViewCursor;
	import mx.core.UIComponent;
	import mx.events.ResizeEvent;
	
	[Event(name="nodeClick", type="controls.TaskStatusChartEvent")]
	
	[Event(name="startTask", type="controls.TaskStatusChartEvent")]
	[Event(name="stopTask", type="controls.TaskStatusChartEvent")]
	public class TaskStatusChart extends UIComponent{
		
		private var _data:ArrayCollection;
		
		private var dataProviderChanged:Boolean;
		
		private var _children:ArrayCollection;
		
		private var _nodes:ArrayCollection;
		
		private var _nodeWidth:Number = 144;
		private var _nodeHeight:Number = 128;
		
		public function TaskStatusChart(){
			_children = new ArrayCollection();	
			_nodes = new ArrayCollection();
			
			addEventListener(ResizeEvent.RESIZE, onResize);
		}
		
		override protected function commitProperties():void{
			super.commitProperties();
		}
		
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			if(dataProviderChanged){
				trace("[TaskStatusChart updateDisplayList] _data = " + _data.length);
				var preNode:TaskStatusChartNode;
				
				
				var len:Number = _data.length;
				
				var horizontalGap:Number = 60;
				
				var maxPerRowNodeCount:Number = Math.round((unscaledWidth - horizontalGap)  / (nodeWidth + horizontalGap));	
				var rowCount:Number = Math.ceil( len / maxPerRowNodeCount );
				
				var startX:Number = 0;
				var startY:Number = 0;
				
				var rowHeight:Number = unscaledHeight / rowCount;
				
				/*
				trace("[TaskStatusChart updateDisplayList] maxPerRowNodeCount = " + maxPerRowNodeCount);
				trace("[TaskStatusChart updateDisplayList] rowCount = " + rowCount);
				trace("[TaskStatusChart updateDisplayList] rowHeight = " + rowHeight);
				*/
				
				if(len < maxPerRowNodeCount){
					startX = (unscaledWidth -  len * (nodeWidth + horizontalGap))/2;
				}else{
					startX = horizontalGap;
				}
				
				startY = (rowHeight - nodeHeight) / 2;
				
				//trace("[TaskStatusChart updateDisplayList] startX = " + startX);
				//trace("[TaskStatusChart updateDisplayList] startY = " + startY);
				
				var counter:Number = 0;	
				var isLeftToRight:Boolean = true;		
				for(var cursor:IViewCursor=_data.createCursor();!cursor.afterLast; cursor.moveNext()){
					var item:Object = cursor.current;
					
					var node:TaskStatusChartNode = new TaskStatusChartNode();
					node.addEventListener(MouseEvent.CLICK, onNodeClick);
					node.addEventListener(TaskStatusChartEvent.START_TASK_MENU_CLICK, onStartTask);
					node.addEventListener(TaskStatusChartEvent.STOP_TASK_MENU_CLICK, onStopTask);
					
					node.width = nodeWidth;
					node.height = nodeHeight;
					
					
					if(!preNode){
						node.x = startX;
						node.y = startY;
					}else{
						var line:LineDescriptor;
						if(isLeftToRight){
							node.x = preNode.x + preNode.width + horizontalGap;
							node.y = preNode.y;
							
							line = new LineDescriptor(
								new Point( preNode.x+preNode.width, preNode.y+preNode.height/2 ), 
								new Point( node.x, node.y+node.height/2 ) 
							);
						}else{
							node.x = preNode.x - node.width - horizontalGap;
							node.y = preNode.y;
							line = new LineDescriptor(
								new Point( preNode.x , preNode.y+(preNode.height/2) ), 
								new Point( node.x +node.width, node.y+(node.height/2) ) 
							);
						}
					
						var currentRow:Number = Math.ceil(counter/maxPerRowNodeCount);
						
						/*
						trace("[TaskStatusChart updateDisplayList] currentRow = " + currentRow);
						trace("[TaskStatusChart updateDisplayList] currentRow % 2 = " + currentRow % 2);
						trace("[TaskStatusChart updateDisplayList] maxPerRowNodeCount*currentRow = " + maxPerRowNodeCount*currentRow);
						trace("[TaskStatusChart updateDisplayList] counter = " + counter);
						trace("[TaskStatusChart updateDisplayList] ---------------");
						*/
						
						if(counter == maxPerRowNodeCount*currentRow){
							if( currentRow % 2 != 0 ){
								node.x = preNode.x;
								node.y = preNode.y + rowHeight;
								isLeftToRight = false;
								line = new LineDescriptor(
									new Point( preNode.x+preNode.width/2, preNode.y+preNode.height ), 
									new Point( node.x+node.width/2, node.y ) 
								);
							}else{
								node.x = preNode.x;
								node.y = preNode.y + rowHeight;
								isLeftToRight = true;
								line = new LineDescriptor(
									new Point( preNode.x+preNode.width/2, preNode.y+preNode.height ), 
									new Point( node.x+node.width/2, node.y ) 
								);
							}
						}
						
						_children.addItem(line);
						addChild(line);
					}
					
					node.data = item;
					node.label = item.taskname;
					
					//trace("[TaskStatusChart updateDisplayList] node = " + node);
					preNode = node;
					
					_children.addItem(node);
					_nodes.addItem(node);
					addChild(node);
					
					counter++;
				}
				
			}
			dataProviderChanged = false;
		}
		public function changeTaskStatus(task:Object):void{
			//trace("[TaskStatusChart changeTaskStatus] task.taskstatus = " + task.taskstatus);
			//trace("[TaskStatusChart changeTaskStatus] task.taskid = " + task.taskid);	
			for(var cursor:IViewCursor = _nodes.createCursor(); !cursor.afterLast; cursor.moveNext()){
				var node:Object = cursor.current;
				var dt:Object = node.data;
				//trace("[TaskStatusChart changeTaskStatus] dt.taskid = " + dt.taskid);	

				if (dt 
					&& dt.taskid == task.taskid
					&& dt.taskstatus != task.taskstatus){
						
					trace("[TaskStatusChart changeTaskStatus] change task '" 
						+ task.taskname + "' status to '"+ task.taskstatus + "'.");	
									
					node.data = task;
				}
			}
		}
		private function createNode(preNode:TaskStatusChartNode, data:Object):void{
			
		}
		public function set dataProvider(value:ArrayCollection):void{
			_data = value;	
			//trace("[TaskStatusChart set dataProvider] value = "+ value);
			dataProviderChanged = true;
			
			removeAllChildren();
			
			invalidateDisplayList();
		}
		
		public function get dataProvider():ArrayCollection{
			return _data;
		}
		
		
		public function set nodeWidth(value:Number):void{
			_nodeWidth = value;
		}

		public function get nodeWidth():Number{
			return _nodeWidth;
		}
		
		public function set nodeHeight(value:Number):void{
			_nodeHeight = value;
		}

		public function get nodeHeight():Number{
			return _nodeHeight;
		}
		
				
		private function removeAllChildren():void{
			_nodes = new ArrayCollection();
			for(var cursor:IViewCursor = _children.createCursor(); !cursor.afterLast; cursor.moveNext()){
				removeChild(cursor.current as DisplayObject);
			}
			
			_children = new ArrayCollection();
		}
		
		private function onNodeClick(event:MouseEvent):void{
			if(willTrigger(TaskStatusChartEvent.NODE_CLICK)){
				dispatchEvent(new TaskStatusChartEvent(TaskStatusChartEvent.NODE_CLICK, event.currentTarget as TaskStatusChartNode));
			}
		}
		
		private function onStartTask(event:TaskStatusChartEvent):void{
			if(willTrigger(TaskStatusChartEvent.START_TASK)){
				dispatchEvent(new TaskStatusChartEvent(TaskStatusChartEvent.START_TASK, event.node));
			}
		}
		
		private function onStopTask(event:TaskStatusChartEvent):void{
			if(willTrigger(TaskStatusChartEvent.STOP_TASK)){
				dispatchEvent(new TaskStatusChartEvent(TaskStatusChartEvent.STOP_TASK, event.node));
			}
		}
		
		private function onResize(event:ResizeEvent):void{
			if(_data){
				dataProvider = _data
			}
		}
		
	}
}